#include "websocket/control_sdk.hpp"
#include <nlohmann/json.hpp>

using namespace WD;
using json = nlohmann::json;

ControlSdk::ControlSdk() {
    web_socket_client_ = std::make_unique<WD::WebSocketClient>(ioc_);
}
ControlSdk::~ControlSdk() {}
// 查询摄像头
std::vector<CameraInfo> ControlSdk::queryCamera()
{
    std::vector<CameraInfo> result;

    auto cams = queryIpCamera("192.168.1.255");
    result.insert(result.end(), cams.begin(), cams.end());

    // 中文打印 fallbackCams 详细信息
    for (const auto& cam : result) {
        std::cout << "摄像头信息:" << std::endl;
        std::cout << "  IP 地址: " << cam.ip << std::endl;
        std::cout << "  ws端口: " << cam.ws_http_port << std::endl;
        std::cout << "  是否需要密码: " << cam.ws_need_secret << std::endl;
        std::cout << "  mac地址: " << cam.mac_addr << std::endl;
        std::cout << "  型号: " << cam.model << std::endl;
        std::cout << "  sn码: " << cam.sn << std::endl;
        std::cout << "  固件版本号: " << cam.version << std::endl;
        // 可根据 CameraInfo 添加更多字段打印
    }
    return result;
}

bool ControlSdk::connectCamera(CameraInfo *camera)
{
    return web_socket_client_->connect(camera->ip);
}

// 连接相机
bool ControlSdk::connectCamera(std::string& ip)
{
    // 使用WebSocket客户端连接相机
    return web_socket_client_->connect(ip);
}

bool ControlSdk::closeCamera(bool isExit)
{
    stopStream();  // 停止推流
    if (web_socket_client_) {
        web_socket_client_->close();
        if (isExit) {
            web_socket_client_.reset();  // 释放 WebSocketClient
        }
        return true;
    }
    return false;
}

bool ControlSdk::getCameraState()
{
    if (!web_socket_client_){
        std::cout << "没连接" << std::endl;
        return false;
    } 
    switch (web_socket_client_->getStatus()) {
        case WD::WebSocketClient::Status::Open:
            return true;
        case WD::WebSocketClient::Status::Connecting:
            std::cout << "连接中！" << std::endl;
            break;
        default:
            std::cout << "其他" << std::endl;
            break;
    }
    return false;
}

void ControlSdk::startStream()
{
    sendSimpleRpc(RPC_START_STREAM);
}

void ControlSdk::stopStream()
{
    sendSimpleRpc(RPC_STOP_STREAM);
}

bool ControlSdk::setImageOutParams(const ImageOutParams& config)
{
    return sendRpc(RPC_CONFIG_OUTPUT, RPC_ID_100, config.to_json());
}

bool ControlSdk::setPpsParams(const PpsConfigParams& config)
{
    return sendRpc(RPC_SET_PPS_CONFIG, RPC_ID_100, config.to_json());
}

bool ControlSdk::setPpsEnable(const bool enable)
{
    return sendRpc(RPC_SET_PPS_ENABLE, RPC_ID_100, makeEnableJson(enable));
}

bool ControlSdk::setGpsParams(const GpsParams &config)
{
    return sendRpc(RPC_SET_GPS_CONFIG, RPC_ID_100, config.to_json());
}
bool ControlSdk::setGpsEnable(const bool enable)
{
    return sendRpc(RPC_SET_GPS_ENABLE, RPC_ID_100, makeEnableJson(enable));
}
bool ControlSdk::setCameraIpParams(const IpConfigParams &config)
{
    return sendRpc(RPC_SET_IP, RPC_ID_100, config.to_json());
} // 抽取公共部分
void ControlSdk::sendSimpleRpc(const std::string& method)
{
    if (!web_socket_client_ || web_socket_client_->getStatus() != WD::WebSocketClient::Status::Open) {
        std::cout << "WebSocket 未连接，无法发送指令！" << std::endl;
        return;
    }
    std::lock_guard<std::mutex> lock(web_socket_mutex_);
    json j_request = {
        {"jsonrpc", "2.0"},
        {"id", RPC_ID_100},
        {"method", method}
    };
    std::string sendMessage = j_request.dump();
    web_socket_client_->send(sendMessage);
    std::cout << "发送指令：" << sendMessage << std::endl;
}

bool ControlSdk::sendRpc(const std::string& method, const std::string& id, const json& params)
{
    if (!web_socket_client_)
    {
        std::cout << "请先连接相机！" << std::endl;
        return false;
    }

    if (web_socket_client_->getStatus() != WD::WebSocketClient::Status::Open)
    {
        std::cout << "WebSocket 连接未打开！" << std::endl;
        return false;
    }
    std::lock_guard<std::mutex> lock(web_socket_mutex_);
    // 构造 JSON-RPC 请求
    json j_request = {
        {"jsonrpc", "2.0"},
        {"id", id},
        {"method", method},
        {"params", params}
    };
    std::string sendMessage = j_request.dump();

    web_socket_client_->send(sendMessage);
    std::cout << "发送信息：" << sendMessage << std::endl;

    // 等待回复
    int waitCount = 0;
    while (waitCount < 200)
    {
        std::string revStr = web_socket_client_->receive();
        if (!revStr.empty())
        {
            // 先打印收到的内容
            std::cout << "收到回复：" << revStr << std::endl;
            try {
                json j_response = json::parse(revStr);
                if (j_response.value("id", "") == id)
                {
                    std::cout << "收到回复：" << revStr << std::endl;
                    if (j_response.value("result", false) == true){
                        std::cout << "收到回复：返回成功" << std::endl;
                        return true;
                    }
                    
                }
            } catch (const std::exception& e) {
                std::cerr << "解析 JSON 错误: " << e.what() << std::endl;
            }
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        waitCount++;
    }

    std::cout << "等待回复超时！" << std::endl;
    return false;
}

// 获取本地IP地址列表
std::vector<std::string> ControlSdk::getLocalIpList()
{
    // 定义一个字符串向量，用于存储IP地址列表
    std::vector<std::string> ipList;
    // 定义一个ifaddrs结构体指针，用于存储网络接口信息
    struct ifaddrs *ifaddr, *ifa;
    // 获取网络接口信息
    if (getifaddrs(&ifaddr) == -1) {
        // 如果获取失败，输出错误信息
        perror("getifaddrs");
        // 返回空IP地址列表
        return ipList;
    }

    // 遍历网络接口信息
    for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
        // 如果网络接口地址为空或者地址类型不是IPv4，则跳过
        if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET)
            continue;
        // 定义一个字符数组，用于存储IP地址
        char host[NI_MAXHOST];
        // 将网络接口地址转换为IP地址
        if (getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in),
                        host, NI_MAXHOST, nullptr, 0, NI_NUMERICHOST) == 0) {
            // 将IP地址添加到IP地址列表中
            ipList.emplace_back(host);
        }
    }
    // 释放网络接口信息
    freeifaddrs(ifaddr);
    // 返回IP地址列表
    return ipList;
}

// 查询IP相机
std::vector<CameraInfo> ControlSdk::queryIpCamera(const std::string &broadcastIp)
{
    std::vector<CameraInfo> result;
    const int PORT = 9999;
    const int TIMEOUT_SEC = 1;

    int sockSend = socket(AF_INET, SOCK_DGRAM, 0);
    int sockRecv = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockSend < 0 || sockRecv < 0) {
        perror("socket");
        return result;
    }   
    // 设置允许广播
    int broadcast = 1;
    setsockopt(sockSend, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));
    setsockopt(sockRecv, SOL_SOCKET, SO_REUSEADDR, &broadcast, sizeof(broadcast));
    // 构造广播地址
    sockaddr_in recvAddr{};
    recvAddr.sin_family = AF_INET;
    recvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    recvAddr.sin_port = htons(PORT);
    if (bind(sockRecv, (sockaddr*)&recvAddr, sizeof(recvAddr)) < 0) {
        perror("bind");
        close(sockSend);
        close(sockRecv);
        return result;
    }

    sockaddr_in destAddr{};
    destAddr.sin_family = AF_INET;
    destAddr.sin_port = htons(PORT);
    inet_pton(AF_INET, broadcastIp.c_str(), &destAddr.sin_addr);
    // 发送 ping 消息
    std::string jsonPing = R"({"jsonrpc":"2.0","id":999,"method":"ping"})";
    sendto(sockSend, jsonPing.c_str(), jsonPing.size(), 0, (sockaddr*)&destAddr, sizeof(destAddr));

    for (int i = 0; i < 10; ++i) {
        fd_set readfds;
        FD_ZERO(&readfds);
        FD_SET(sockRecv, &readfds);

        timeval timeout{};
        timeout.tv_sec = TIMEOUT_SEC;
        timeout.tv_usec = 0;

        int ret = select(sockRecv + 1, &readfds, nullptr, nullptr, &timeout);
        if (ret <= 0)
            break;

        if (FD_ISSET(sockRecv, &readfds)) {
            char buffer[1024] = {0};
            sockaddr_in senderAddr{};
            socklen_t senderLen = sizeof(senderAddr);
            ssize_t len = recvfrom(sockRecv, buffer, sizeof(buffer) - 1, 0,
                                   (sockaddr*)&senderAddr, &senderLen);
            if (len <= 0) continue;

            buffer[len] = '\0';
            std::string recvStr(buffer);

            try {
                json j = json::parse(recvStr);
                if (j.contains("id") && j["id"] == 999 && j.contains("result")) {
                    auto& res = j["result"];
                    CameraInfo cam;
                    cam.sn = res.value("sn", "");
                    cam.model = res.value("model", "");
                    cam.mac_addr = res.value("mac_addr", "");
                    cam.ip = res.value("ip", "");
                    cam.connect_client_ip = res.value("ping_ip", "");
                    cam.version = res.value("version", "");
                    cam.ws_http_port = res.value("ws_http_port", 0);
                    cam.ws_need_secret = res.value("ws_need_secret", false);
                    
                    // 避免重复添加相机
                    bool exists = false;
                    for (const auto& c : result) {
                        if (c.ip == cam.ip) {
                            exists = true;
                            break;
                        }
                    }
                    if (!exists)
                        result.push_back(cam);
                }
            } catch (const std::exception& e) {
                std::cerr << "JSON parse error: " << e.what() << std::endl;
            }
        }
    }

    close(sockSend);
    close(sockRecv);
    return result;
}
